/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_HASSLOTS_H
#define M_HASSLOTS_H

#include "lfqueue.h"
#include "lffreelist.h"

#include "slotmessage.h"

namespace Engine
{
	/**
	*   Base type for all classes which have slots.
	*/
	class HasSlots
	{
	public:

		/**
		*   Constructor.
		*/
		HasSlots():m_Pool(1000),m_Messages(m_Pool.NewInstance()){}

		/**
		*   Destructor.
		*/
		virtual ~HasSlots()
		{
			ClearQueue();
			if(LockFree::node<RefPtr<SlotMessageBase> >* pNode = m_Messages.GetHead())
			{
				m_Pool.FreeInstance(pNode);
			}
		}

		/**
		*   Remove all item from message queue.
		*/
		void ClearQueue()
		{
			while(LockFree::node<RefPtr<SlotMessageBase> >* pNode = m_Messages.Remove())
			{
				m_Pool.FreeInstance(pNode);
			}
		}

		/**
		*   Run all callbacks associated with messages.
		*/
		void DispatchMessages() const
		{
			while(LockFree::node<RefPtr<SlotMessageBase> >* pNode = m_Messages.Remove())
			{
				if(!pNode->value.IsNull())
					pNode->value->Fire();
				m_Pool.FreeInstance(pNode);
			}
		}

		/**
		*   Add new message.
		*/
		void AddMessage(RefPtr<SlotMessageBase> pMsg)
		{
			LockFree::node<RefPtr<SlotMessageBase> >* pNode = m_Pool.NewInstance();
			pNode->value = pMsg;
			m_Messages.Add(pNode);
		}

	private:

		HasSlots(const HasSlots& rhs);
		HasSlots& operator=(const HasSlots& rhs);

	private:

		mutable LockFree::FreeList<LockFree::node<RefPtr<SlotMessageBase> > > m_Pool;     ///< Object for allocating new messages nodes.
		mutable LockFree::Queue<RefPtr<SlotMessageBase> >                       m_Messages; ///< Object for stroing messages queue.
	};
}

#endif
